#include <iostream>
#include <Windows.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#include "stock_data.h"
#include <vector>
#include <array>
#include "timeline.h"
#include "money_manager.h"

#include "position_manager.h"
#include "volume_chart.h"
#include "stock_data_loader.h"
#include "stock_analyzer.h"
#include "stock_analyzer_2.h"
#include <functional>
#include "gambler.h"
#include "kline_lib.h"
#include "KDJ_chart.h"
#include "mouse_pos.h"
#include "MACD_chart.h"
#include <shlobj.h>// 用于导出文件
#include <commdlg.h> // 用于导出文件 包含 GetSaveFileName 函数
#include <fstream> // 包含文件流操作的头文件
#include <cmath> // 用于判断 胜率为-nan. 
#include <algorithm>

const int g_main_window_width = 800;
const int g_main_window_height = 1000;
// 日期范围定为120, 用于图表的显示, 图表上是90天  为了不与图表
const int date_range = 120;
// 预设的开始时间
const std::string g_start_date = "2019-01-01";
// 起步时的资产占比:
const float g_found_starting_rate = 0.25;
// 小号字体:
static ImFont* g_fontSmall = NULL;


// 全局变量
std::vector<StockData> g_stockData;
// 是否需要重新渲染 初始值为true表示首次加载时需要渲染
int g_need_render = 2;
// 当前正在分析的股票,显示的股票的股票代码
std::string g_current_stock_code;


// 全局的时间线
Timeline g_timeline;

// 对应每一只股票的分析器
struct two_analyzer
{
    StockAnalyzer *analyzer;
    stock_analyzer_2 *analyzer2;
};
std::map<std::string, two_analyzer> g_analyzer_map;

// 赌徒
std::vector<Gambler> g_gamblers;


// 打开文件保存对话框，返回用户选择的保存路径（包括文件名）
std::string OpenSaveFileDialog() {
    std::string savePath;

    // 初始化 OPENFILENAME 结构
    OPENFILENAME ofn;
    char szFile[MAX_PATH] = {0}; // 用于存储用户选择的路径和文件名

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = nullptr; // 无父窗口
    ofn.lpstrFile = szFile;  // 存储路径和文件名的缓冲区
    ofn.nMaxFile = MAX_PATH; // 缓冲区大小
    ofn.lpstrFilter = "All Files\0*.*\0Text Files\0*.TXT\0"; // 文件类型过滤器
    ofn.nFilterIndex = 1; // 默认过滤器
    ofn.lpstrFileTitle = nullptr; // 不显示文件标题
    ofn.lpstrInitialDir = nullptr; // 默认目录
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; // 路径必须存在，覆盖时提示

    // 打开文件保存对话框
    if (GetSaveFileName(&ofn)) {
        savePath = szFile; // 获取用户选择的路径和文件名
    }

    return savePath;
}


// 日期标签:
void label_today()
{
    static bool is_first_time = true;
    static std::string current_date=g_start_date;
    if(is_first_time)
    {
        std::cout << "#60 日期标签 注册回调函数" << std::endl;
        is_first_time = false;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) 
        {
            // std::cout<<"日期:"<< date <<std::endl;
            current_date = date;
        });
    }

    // 创建窗口，禁用滚动条
    ImVec2 lable_size = ImVec2(400, 70);// 标签大小
    ImVec2 lable_pos = ImVec2(80, 5);// 子窗口位置
    ImGui::SetNextWindowSize(lable_size);
    ImGui::SetNextWindowPos(lable_pos);
    ImGui::Begin("label_today", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImGui::Text(current_date.c_str());
    // 创建输入框
    ImGui::SetNextWindowPos(ImVec2(200, 0));
    static char inputText[128] = "";
    std::function _f = [](){
        // 当按钮被按下时，处理输入框的内容
        std::string inputContent = inputText;
        g_timeline.setDate(inputContent);
        // 清空输入框
        memset(inputText, 0, sizeof(inputText));
    };
    if(ImGui::InputText("例如:2025-04-02", inputText, IM_ARRAYSIZE(inputText)
                          , ImGuiInputTextFlags_EnterReturnsTrue
        ))
    {
        _f();
    }
    if (ImGui::Button("跳转日期")) {
        _f();
    }
    
    ImGui::End();
}

// K线绘制
void draw_K_line()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#117 K线绘制 注册回调函数" << std::endl;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) {
            // 设置K线的起止时间
            setDateRange(Timeline::getNDaysAgo(date,date_range), date);
            // 更新K线数据 这里不绘制, 更新给其它模块用
            updateKLineData();
        });
        is_first_time = false;
        // 设置K线的起止时间
        setDateRange(Timeline::getNDaysAgo(std::string(g_start_date),date_range), g_start_date);
    }
    // 创建 ImGui 窗口
    ImVec2 sub_window_size = ImVec2(400, 195);// 子窗口大小
    ImVec2 sub_window_pos = ImVec2(80, 80);// 子窗口位置
    ImGui::SetNextWindowSize(sub_window_size);
    ImGui::SetNextWindowPos(sub_window_pos);
    ImGui::Begin("Stock K Line",NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 pos = ImGui::GetCursorScreenPos();// 子窗口的起始位置
    //ImVec2 size = ImVec2(ImGui::GetContentRegionAvail().x, 300.0f);// 子窗口的宽度
    drawKLine(ImGui::GetWindowDrawList(), pos, sub_window_size);
    ImGui::End();
}

// 绘制MACD
void draw_MACD()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        is_first_time=false;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) {
            // 设置MACD的起止时间
            setDateRangeMACD(Timeline::getNDaysAgo(date,date_range), date); 
        });
        // 设置最初的起止时间
        setDateRangeMACD(Timeline::getNDaysAgo(std::string(g_start_date),date_range), g_start_date);
    }
    ImVec2 sub_window_size = ImVec2(400, 195);// 子窗口大小
    ImVec2 sub_window_pos = ImVec2(80, 280);// 子窗口位置
    ImGui::SetNextWindowSize(sub_window_size);
    ImGui::SetNextWindowPos(sub_window_pos);
    ImGui::Begin("MACD",NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 pos = ImGui::GetCursorScreenPos();// 子窗口的起始位置    
    drawMACDChart(ImGui::GetWindowDrawList(), pos, sub_window_size);
    ImGui::End();
}

void sub_window_volume()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#60 成交量子窗口 注册回调函数" << std::endl;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) {
            // 设置成交量的起止时间
            setDateRangeVolume(Timeline::getNDaysAgo(date,date_range), date);
        });
        is_first_time = false;
        // 设置K线的起止时间
        // std::cout << "#60 成交量子窗口 注册回调函数 设置K线的起止时间 开始" << std::endl;
        setDateRangeVolume(Timeline::getNDaysAgo(g_start_date,date_range), g_start_date);
        // std::cout << "#60 成交量子窗口 注册回调函数 设置K线的起止时间 完毕" << std::endl;
    }
    // 创建窗口，禁用滚动条
    ImVec2 lable_size = ImVec2(400, 180);// 标签大小
    ImVec2 lable_pos = ImVec2(80, 480);// 子窗口位置
    ImGui::SetNextWindowSize(lable_size);
    ImGui::SetNextWindowPos(lable_pos);
    ImGui::Begin("Volume", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 pos = ImGui::GetCursorScreenPos();// 子窗口的起始位置
    // 绘制"成交量"标题文字
    ImGui::Text("成交量");
    drawVolumeChart(ImGui::GetWindowDrawList(), pos, ImVec2(400, 180));
    ImGui::End();
}

// KDJ绘制
void draw_KDJ() {
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#117 KDJ绘制 注册回调函数" << std::endl;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) {
            // 设置起止时间
            setDateRangeForKDJ(Timeline::getNDaysAgo(date,date_range), date);
        });
        is_first_time=false;
        // 设置起止时间 (第一次)
        setDateRangeForKDJ(Timeline::getNDaysAgo(std::string(g_start_date),date_range), g_start_date);
    }
    // 创建 ImGui 窗口
    ImVec2 sub_window_size = ImVec2(400, 180);
    ImVec2 sub_window_pos = ImVec2(80, 665);
    ImGui::SetNextWindowSize(sub_window_size);
    ImGui::SetNextWindowPos(sub_window_pos);
    ImGui::Begin("KDJ", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 pos = ImGui::GetCursorScreenPos();// 子窗口的起始位置
    ImGui::Text("KDJ");
    drawKDJLine(ImGui::GetWindowDrawList(), sub_window_pos, sub_window_size);
    ImGui::End();
}


void button_next_day()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#105 下一天按钮 注册回调函数" << std::endl;
        g_timeline.reset();
        is_first_time = false;
        // 注册回调函数
        g_timeline.registerCallback([](const std::string& date) {
            //std::cout << "日期变化到: " << date << std::endl;
            // 在这里可以触发其他模块的更新
            g_need_render=2;
        });
    }

    // 按钮:
    ImVec2 button_size = ImVec2(400, 100);// 按钮大小
    ImVec2 button_pos = ImVec2(80, 855);// 子窗口位置
    ImGui::SetNextWindowSize(button_size);
    ImGui::SetNextWindowPos(button_pos);
    ImGui::Begin("button_next_day", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 windowSize = ImGui::GetWindowSize();
    if (ImGui::Button("下一天", windowSize)) {
        //std::cout << "Button clicked! 下一天按钮" << std::endl;
        g_timeline.advanceToNextDay();
    }
    ImGui::End();
}

// 左侧部分_自动按钮
void button_auto()
{
    // 状态机:
    static u_short _state = 0;// 0:非自动 >0 自动
    static std::string display_text;
    switch(_state)
    {
    case 0:
        display_text="自动";
        break;
    case 1:
        display_text="停止";
        ++_state;
        break;
    }
    if(_state>0)
    {
        g_need_render=2;// 下一帧还自动执行
        // 切到下一天:
        g_timeline.advanceToNextDay();
    }

    ImVec2 _size = ImVec2(70, 70);
    ImVec2 _pos = ImVec2(5, 5);// 子窗口位置
    ImGui::SetNextWindowSize(_size);
    ImGui::SetNextWindowPos(_pos);
    ImGui::Begin("auto_button", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 windowSize = ImGui::GetWindowSize();
    if (ImGui::Button(display_text.c_str(), windowSize)) {
        // std::cout << "Button clicked! 自动" << std::endl;
        if(0==_state)_state=1;
        else if(_state>0)_state=0;
        g_need_render=1;// 下一帧还自动执行
    }
    ImGui::End();
}

// 左侧部分_换显示的股票图表
void button_change_stock()
{
    // 按钮:
    ImVec2 _size = ImVec2(70, 70);
    ImVec2 _pos = ImVec2(5, 80);// 子窗口位置
    ImGui::SetNextWindowSize(_size);
    ImGui::SetNextWindowPos(_pos);
    ImGui::Begin("_change_stock", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 windowSize = ImGui::GetWindowSize();
    // 创建输入框
    ImGui::SetNextWindowPos(ImVec2(200, 0));
    ImGui::SetNextWindowSize(_size);
    static char inputText[128] = "";
    std::function _f=[]()
    {
        std::cout<<"点击的按钮\t"<<inputText << std::endl;
        
        std::vector<std::string> stock_codes = getAllStockCodes();
        std::string stock_found;
        for(std::string &str: stock_codes)
        {
            if(0==str.find(inputText))
            {
                stock_found=str;
                break;
            }
        }// END for
        if(stock_found.empty())
        {
            std::cout<<"#334未找到股票"<<std::endl;
        }
        else
        {
            g_current_stock_code = stock_found;
            two_analyzer &analyzers = g_analyzer_map[stock_found];
            StockAnalyzer *analyzer = analyzers.analyzer;
            stock_analyzer_2 *analyzer2 = analyzers.analyzer2;
            std::vector<StockData> &stock_data = analyzer->getStockData();
            
            // 设置数据
            initKLineData(stock_data);
            setMACDData(stock_data);
            initVolumeChart();
            setVolumeData(stock_data);
            setKDJChartData(stock_data);       
            // 获取当前日期（格式：YYYY-MM-DD）
            std::string date = g_timeline.getCurrentDate();
            // 设置K线的起止时间
            setDateRange(Timeline::getNDaysAgo(date,date_range), date);            
            // 更新K线数据 这里不绘制, 更新给其它模块用
            updateKLineData();
            // 设置起止时间
            setDateRangeForKDJ(Timeline::getNDaysAgo(date,date_range), date);
            // 设置MACD的起止时间
            setDateRangeMACD(Timeline::getNDaysAgo(date,date_range), date); 
            // 设置成交量的起止时间
            setDateRangeVolume(Timeline::getNDaysAgo(date,date_range), date);

            g_need_render=10;
        }
    };
    if (
        ImGui::InputText(
            "##输入代码", inputText, IM_ARRAYSIZE(inputText), ImGuiInputTextFlags_EnterReturnsTrue
        )
    ) 
    {
        _f();
    }
    if (ImGui::Button("换股票",ImVec2(windowSize.x, windowSize.y*.5))) {
        _f();
    }
    ImGui::End();

}

std::array<std::string, 2> splitByDot(const std::string& str) {
    size_t dotPos = str.find('.');
    
    // 检查是否存在小数点
    if (dotPos == std::string::npos) {
        throw std::invalid_argument("字符串中没有找到小数点");
    }
    
    // 检查是否只有一个小数点
    size_t secondDotPos = str.find('.', dotPos + 1);
    if (secondDotPos != std::string::npos) {
        throw std::invalid_argument("字符串中存在多个小数点");
    }
    
    // 分割字符串
    return {str.substr(0, dotPos), str.substr(dotPos + 1)};
}

// 左侧部分_导出按钮
void button_export()
{
    ImVec2 _size = ImVec2(70, 100);
    ImVec2 _pos = ImVec2(5, 855);// 子窗口位置
    ImGui::SetNextWindowSize(_size);
    ImGui::SetNextWindowPos(_pos);
    ImGui::Begin("export", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImVec2 windowSize = ImGui::GetWindowSize();
    if(ImGui::Button("导出",windowSize))
    {
        // std::string str_path = OpenSaveFileDialog();
        // if(!str_path.empty())
        {
            //std::cout<<"导出路径:"<<str_path <<std::endl;
            // // 写到文件中:
            // // 打开文件
            // std::ofstream outFile(str_path);
            // if (!outFile.is_open()) {
            //     std::cerr << "无法打开文件！" << std::endl;
            // }
            // else
            // {
            //     // 在导出点遍历所有股票对应的analyzer_2对象
            //     size_t count_all=0;
            //     double sum_of_win_rate=0;
            //     double sum_of_profit_ratio=0;
            //     double sum_of_loss_ratio=0;
            //     for(auto iterA = g_analyzer_map.begin();iterA!=g_analyzer_map.end();++iterA)
            //     {
            //         two_analyzer &analyzers = iterA->second;
            //         stock_analyzer_2 *analyzer2=analyzers.analyzer2;
            //         double win_rate = analyzer2->getWinRate();
            //         if(!isnan(win_rate))
            //         {
            //             sum_of_win_rate+=win_rate ;
            //             ++count_all;
            //         }
            //         sum_of_profit_ratio += analyzer2->getProfitRatio();
            //         sum_of_loss_ratio += analyzer2->getLossRatio();
            //     }// END for
            //     // 将浮点数写入文件
            //     outFile << sum_of_win_rate/count_all<<"\n";
            //     outFile << "总胜率:"<< sum_of_win_rate<<"\n";
            //     outFile << "count_all:"<<count_all<<"\n";
            //     outFile << "总利润比例:"<< sum_of_profit_ratio<<"\n";
            //     outFile << "总亏损比例:"<< sum_of_loss_ratio<<"\n";
            //     outFile << "能赚多少比例:"<< sum_of_profit_ratio/sum_of_loss_ratio<<"\n";
            //     // 关闭文件
            //     outFile.close();
            // }

            // 只在控制台输出
            {
                // 在导出点遍历所有股票对应的analyzer_2对象
                size_t count_all=0;
                double sum_of_win_rate=0;
                double sum_of_profit_ratio=0;
                double sum_of_loss_ratio=0;
                std::vector<std::pair<std::string,double>> vec_win_rate;
                for(auto iterA = g_analyzer_map.begin();iterA!=g_analyzer_map.end();++iterA)
                {
                    two_analyzer &analyzers = iterA->second;
                    stock_analyzer_2 *analyzer2=analyzers.analyzer2;
                    double win_rate = analyzer2->getWinRate();
                    if(!isnan(win_rate))
                    {
                        sum_of_win_rate+=win_rate ;
                        ++count_all;
                    }
                    sum_of_profit_ratio += analyzer2->getProfitRatio();
                    sum_of_loss_ratio += analyzer2->getLossRatio();

                    vec_win_rate.push_back(std::make_pair(iterA->first,win_rate));
                }// END for
                // 胜率排序:
                std::sort(vec_win_rate.begin(),vec_win_rate.end(),[](const std::pair<std::string,double>& a,const std::pair<std::string,double>& b)
                {
                    return a.second>b.second;
                });

                // std::ofstream ofs("win_rate.txt");
                // for(size_t i=0;i<vec_win_rate.size()&&i<100;++i)
                // {
                //     ofs<<"\""<<vec_win_rate[i].first<<"\""<<",";
                // }
                // ofs.close();

                // 将浮点数写入文件
                std::cout << "胜率:"<<sum_of_win_rate/count_all<<"\n";
                std::cout << "总胜率:"<< sum_of_win_rate<<"\n";
                std::cout << "count_all:"<<count_all<<"\n";
                std::cout << "总利润比例:"<< sum_of_profit_ratio<<"\n";
                std::cout << "总亏损比例:"<< sum_of_loss_ratio<<"\n";
                std::cout << "能赚多少比例:"<< sum_of_profit_ratio/sum_of_loss_ratio<<"\n";
            }
        
            // // 导出大涨数据:
            // std::ofstream ofs("big_increase.csv");
            // {
            //     for(auto iterA = g_analyzer_map.begin();iterA!=g_analyzer_map.end();++iterA)
            //     {
            //         two_analyzer &analyzers = iterA->second;
            //         stock_analyzer_2 *analyzer2=analyzers.analyzer2;
            //         const std::vector<std::string> &big_rise_time = analyzer2->getBigRiseTime();
            //         const std::vector<before_big_rise_trait> &big_rise_trait = analyzer2->getBeforeBigRiseTraitRecord();
            //         if(big_rise_time.size())
            //         {
            //             ofs<<iterA->first<<",";
            //             for(size_t i=0;i<big_rise_trait.size();++i)
            //             {
            //                 const std::string &time = big_rise_time[i];
            //                 const before_big_rise_trait &trait = big_rise_trait[i];
            //                 ofs<<time<<"|";
            //                 ofs<<(trait.price_less_than_ma120?"在120均线以下":"")<<"|";
            //                 ofs<<(trait.has_small_volume_sellout?"有缩量下跌":"")<<"|";
            //                 ofs<<(trait.macd_depart_speed_up_and_close_to_one?"MACD速度急速上破1":"")<<"|";
            //                 ofs<<"连续背离天数:"<<trait.macd_depart_speed_up_days<<"|";
            //                 ofs<<"最大背离值:"<<trait.max_macd_depart_value_in_15_days<<"|";
            //                 ofs<<",";
            //             }
            //             ofs<<"\n";                    
            //         }
            //     }
            //     ofs.close();
            // }

            // 导出赚了多少:
            std::ofstream ofs("earn_money.csv");
            std::string all_stock_number = "";// 所有股票的代码, 用于在东方财富网取所有的市值
            for(auto iterA = g_analyzer_map.begin();iterA!=g_analyzer_map.end();++iterA)
            {
                two_analyzer &analyzers = iterA->second;
                stock_analyzer_2 *analyzer2=analyzers.analyzer2;
                double earn_money = analyzer2->getProfit();
                // 买入点与卖出点:
                const std::vector<std::string> &_buy_and_sell = analyzer2->getBuyAndSell();
                const std::vector<int> & _buy_or_sell = analyzer2->getBuyOrSell();
                ofs<<iterA->first<<",";
                // ofs<<earn_money<<",";
                // for(size_t i=0;i<_buy_and_sell.size();++i)
                // {
                //     if(_buy_or_sell[i]==1)
                //     {
                //         ofs<<"买"<<_buy_and_sell[i]<<",";
                //     }
                //     else
                //     {
                //         ofs<<"卖"<<_buy_and_sell[i]<<",";
                //     }
                // }    
                
                // 导出排序依据:
                std::string str_current_date = g_timeline.getCurrentDate();
                stock_analyzer_data data = analyzeStockData(analyzers.analyzer,str_current_date.c_str());
                if(data.new_lows_and_bottoms_diverge)
                {
                    ofs<<"新低和底部背离,";
                }
                else
                {
                    ofs<<"无,";
                }
                // macd_ma30_level:
                {
                    ofs<<data.price_ma30_level<<",";
                }
                // macd_depart:

                ofs<<"\n";

                // // 格式化为东方财富网的股票代码:英文字母在前
                // std::array<std::string, 2> split_restul= splitByDot(iterA->first);
                // std::string stock_code = split_restul[1]+split_restul[0];
                // if(split_restul[1]=="BJ")
                // {
                //     stock_code = "BJ/"+split_restul[0];
                // }
                // all_stock_number+="\""+stock_code+"\""+",";
                all_stock_number+="\""+iterA->first+"\""+",";
            }
            std::cout<<"输出东方财富网的股票代码格式:"<<std::endl;
            std::cout<<all_stock_number<<std::endl;
        }
    }
    ImGui::End();
}


// 右上角显示资金
void show_fund()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#157 资金子窗口 注册回调函数" << std::endl;
        is_first_time = false;
        // 初始化资金管理器（设置20万初始资金）
        initMoneyManager();
    }

    // 获取当前资金
    double current_money = getCurrentMoney();
    // 计算总资产:
    double total_stock_value = getTotalValue();
    double total_money = total_stock_value + current_money;
    double _stock_position = total_stock_value/total_money;

    // 创建窗口，禁用滚动条
    ImVec2 lable_size = ImVec2(200, 70);// 标签大小
    ImVec2 lable_pos = ImVec2(485, 5);// 子窗口位置
    ImGui::SetNextWindowSize(lable_size);
    ImGui::SetNextWindowPos(lable_pos);
    ImGui::Begin("资金", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImGui::Text("当前资金: %.2f", current_money);
    //ImFont* fontSmall = io.Fonts->AddFontFromFileTTF("simhei.ttf", 14.0f, nullptr, io.Fonts->GetGlyphRangesChineseFull());
    ImGui::PushFont(g_fontSmall);
    ImGui::Text("总资产: %.0f 仓位: %.0f%%", total_money , _stock_position*100);
    ImGui::PopFont();
    ImGui::End();

}

// 右侧_显示持仓信息
void show_position_info()
{
    static bool is_first_time = true;
    if(is_first_time)
    {
        std::cout << "#149 持仓信息子窗口 注册回调函数" << std::endl;
        is_first_time = false;
        // // 注册回调函数
        // g_timeline.registerCallback_after([](const std::string& date) {
        //     // 获取当前持仓信息
        //     StockPosition pos1;
        //     if(getStockPosition("600104.SH", &pos1))
        //     {
        //         // std::cout << "持仓信息: " << pos1.quantity << " 手, 价格: " << pos1.currentPrice << std::endl;
        //     }
        //     else
        //     {
        //         pos1.quantity = 0;
        //     }
        //     AdjustParams params;
        //     params.currentPrice = getLastClosePrice();
        //     params.availableCash = getCurrentMoney();
        //     params.currentPosition = pos1.quantity;
        //     params.ma5 = getMA5();
        //     params.ma10 = getMA10();
        //     params.ma20 = getMA20();
        //     params.lastMa5 = getLastMA5();
        //     params.lastMa10 = getLastMA10();
        //     params.lastMa20 = getLastMA20();
        //     params.ma90DaysHeigh = get90DaysHeigh();
        //     params.ma90DaysLow = get90DaysLow();
        //     params.lastDayPrice = getLastDayPrice();
        //     params.isHammerOrStar = isHammerOrStar();
        //     params.isLargeVolumeWashout = isLargeVolumeWashout();
        //     params.isLargeVolumeSellout = isLargeVolumeSellout();
        //     params.date = date;
        //     params.buyCallback = [](int quantity, double price) {
        //         std::cout << "买入: " << quantity << " 手, 价格: " << price << std::endl;
        //         // 计算买入金额
        //         double amount = quantity * price;
        //         // 检查资金是否足够 减少资金
        //         if (decreaseMoney(amount, "买入600104.SH")) {
        //             // 更新持仓信息
        //             updateStockPosition("600104.SH", quantity, price);
        //         }
        //     };
        //     params.sellCallback = [](int quantity, double price) {
        //         std::cout << "卖出: " << quantity << " 手, 价格: " << price << std::endl;
        //         // 更新持仓信息
        //         if(decreaseStockPosition("600104.SH", quantity)) {
        //             // 增加资金
        //             double amount = quantity * price;
        //             // 印花税:
        //             double stamp_duty = amount * 0.0005;
        //             if(stamp_duty<5)stamp_duty=5;
        //             increaseMoney(amount-stamp_duty, "卖出600104.SH");
        //         }
        //     };
        //     adjustPosition(&params);
        //     g_need_render=1;
        // });
        g_timeline.registerCallback_after([](const std::string& date) {
            // 分析出的买入点
            // std::cout<<"#482 registerCallback_after"<<std::endl;
            // std::vector<std::string> buy_stock_codes;
            std::map<std::string, buy_or_sell> buy_stock_codes_price;
            // 分析出的卖出点
            // std::vector<std::string> sell_stock_codes;
            std::map<std::string, double> sell_stock_codes_price;

            // size_t call_times = 0;

            std::vector<std::string> stock_codes = getAllStockCodes();

            // 分析每只股票
            for(auto& stock : stock_codes)
            {
                if(!g_analyzer_map.contains(stock))continue;

                two_analyzer &analyzers = g_analyzer_map[stock];
                // std::cout<<"#494 分析"<<stock<<std::endl;
                stock_analyzer_data data = analyzeStockData(analyzers.analyzer, date.c_str());
                // std::cout<<"#494 分析完成" << "\t计数:"<< call_times<<std::endl;
                data.date = date;
                // ++call_times;
                // std::cout<<"#499 main adjustPosition"<<std::endl;
                buy_or_sell result = analyzers.analyzer2->adjustPosition(&data);
                // std::cout<<"#499 main adjustPosition END"<<std::endl;
                if(result.buy)
                {
                    // std::cout << "买入: " << stock << " " << 100 << " 手, 价格: " << result.price << std::endl;
                    buy_stock_codes_price[stock] = result;
                    // if (decreaseMoney(100*result.price, stock.c_str())) {
                    //     // 更新持仓信息
                    //     updateStockPosition(stock.c_str(), 100, result.price);
                    // }
                    std::cout<<stock<<"该买"<<std::endl;
                }

                if(result.sell)
                {
                    // std::cout << "卖出: " << stock << " " << 100 << " 手, 价格: " << result.price << std::endl;
                    sell_stock_codes_price[stock] = result.price;
                    // if(decreaseStockPosition(stock.c_str(), 100)) {
                    //     // 印花税:
                    //     double amount = 100*result.price;
                    //     double stamp_duty = amount * 0.0005;
                    //     if(stamp_duty<5)stamp_duty=5;
                    //     increaseMoney(amount-stamp_duty, stock.c_str());
                    // }
                    std::cout<<stock<<"该卖"<<std::endl;
                }
            }// END for

            // 排序
            std::vector<std::pair<std::string, buy_or_sell>> sorted_buy_stock_codes_price;
            for(auto& pair : buy_stock_codes_price)
            {
                //if(pair.second.arrange_value<.02)// 这个判断,胜率加了10%, 加到50%了
                {
                    sorted_buy_stock_codes_price.push_back(pair);
                }
            }
            // std::sort(sorted_buy_stock_codes_price.begin(), sorted_buy_stock_codes_price.end(), [](const std::pair<std::string, buy_or_sell>& a, const std::pair<std::string, buy_or_sell>& b) {
            //     return a.second.arrange_value > b.second.arrange_value;
            // });

            // for(std::pair<std::string, buy_or_sell> &iterA : sorted_buy_stock_codes_price)
            // {
            //     std::cout<<"股票:"<< iterA.first
            //     <<"\t排序值:"<< iterA.second.arrange_value<<std::endl;
            // }

            // std::cout<<"analyzer2->adjustPosition  调用次数:"<<call_times<<std::endl;
            
            // std::cout<<"#524 registerCallback_after"<<std::endl;
            // BEGIN 赌徒
            size_t buy_index = 0;
            // 先处理一遍卖出, 再处理一遍买入, 这样就保证不会出现错过股票的情况
            for(Gambler &gambler : g_gamblers)
            {
                std::string stock_code_was_hold = gambler.getCurrentStockCode();
                
                if(!stock_code_was_hold.empty())
                {
                    if(sell_stock_codes_price.empty())
                    {
                        continue;
                    }

                    for(auto& sell_stock_code : sell_stock_codes_price)
                    {
                        if(sell_stock_code.first==stock_code_was_hold)
                        {
                            // 卖出一只:
                            std::string stock_code = sell_stock_code.first;
                            double price = sell_stock_code.second;

                            int quantity = 100;
                            gambler.sell(stock_code, price, quantity);
                            std::cout << date << "赌徒卖出: " << stock_code << " " << quantity << " 手, 价格: " << price << std::endl;
                            if(decreaseStockPosition(stock_code.c_str(), quantity)) {
                                // 印花税:
                                double amount = quantity*price;
                                double stamp_duty = amount * 0.0005;
                                if(stamp_duty<5)stamp_duty=5;
                                increaseMoney(amount-stamp_duty, stock_code.c_str());
                            }
                            break;
                        }
                    }
                }
            }
            
            // 在没有买卖的情况下,更新价格: sorted_buy_stock_codes_price
            for(const std::pair<std::string, buy_or_sell> &pair : sorted_buy_stock_codes_price)
            {
                const std::string& stock_code = pair.first;
                const float stock_price = pair.second.price;
                updateStockPrice(stock_code.c_str(),stock_price);
            }
            // 计算总资产:
            double total_stock_value = getTotalValue();
            double total_money = total_stock_value + getCurrentMoney();
            double _stock_position = total_stock_value/total_money;

            // 处理买入:
            for(Gambler &gambler : g_gamblers)
            {
                std::string stock_code_was_hold = gambler.getCurrentStockCode();
                if(stock_code_was_hold=="" && _stock_position<g_found_starting_rate )
                {
                    if(buy_stock_codes_price.empty())
                    {
                        continue;
                    }
                    // 买入一只:
                    // std::string stock_code = buy_stock_codes_price.begin()->first;
                    // double price = buy_stock_codes_price.begin()->second.price;
                    // buy_stock_codes_price.erase(stock_code);
                    if(buy_index<sorted_buy_stock_codes_price.size())
                    {
                        std::string stock_code =  sorted_buy_stock_codes_price[buy_index].first;
                        double price = sorted_buy_stock_codes_price[buy_index].second.price;

                        int quantity = gambler.buy(stock_code, price);
                        std::cout << date << "赌徒买入: " << stock_code << " " << quantity << " 手, 价格: " << price << "\t排序值:"<< sorted_buy_stock_codes_price[buy_index].second.arrange_value << std::endl;
                        // for(const std::pair<std::string, buy_or_sell> &pair: sorted_buy_stock_codes_price)
                        // {
                        //     std::cout<<"\t 排序值:"<< pair.second.arrange_value <<std::endl;
                        // }
                        if (decreaseMoney(quantity*price, stock_code.c_str())) {
                            // 更新持仓信息
                            updateStockPosition(stock_code.c_str(), quantity, price);
                        }
                        ++buy_index;
                    }
                }
                else
                {
                    for(const std::pair<std::string, buy_or_sell> &pair : sorted_buy_stock_codes_price)
                    {
                        const std::string &stock_code =  pair.first;
                        if(stock_code==stock_code_was_hold)
                        {
                            if(pair.second.buy)
                            {
                                double price = pair.second.price;
                                int quantity = gambler.buy(stock_code, price);
                                if (decreaseMoney(quantity*price, stock_code.c_str())) {
                                    std::cout << date << "赌徒加仓: " << stock_code << " " << quantity << " 手, 价格: " << price << "\t排序值:"<< sorted_buy_stock_codes_price[buy_index].second.arrange_value << std::endl;
                                    // 更新持仓信息
                                    updateStockPosition(stock_code.c_str(), quantity, price);
                                    ++buy_index;
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }                    
                    }// END for
                }
            }
            
            // // 输出赌徒的赢率
            // // if(g_gamblers.size()>=3)
            // // {
            // //     std::cout << date<< "\t赌徒的赢率: " << g_gamblers[0].getWinRate()<<"\t"<<g_gamblers[1].getWinRate()<<"\t"<<g_gamblers[2].getWinRate() << std::endl;
            // // }
            // std::cout << "赌徒:"<<std::endl;
            // for(Gambler &gambler : g_gamblers)
            // {
            //     if(isnan(gambler.getWinRate()))continue;
            //     std::cout << date<< "\t赢率: " << gambler.getWinRate() << std::endl;
            // }
            // // END 赌徒
        });

    }

    // 创建窗口，禁用滚动条
    ImVec2 lable_size = ImVec2(200, 195);// 标签大小
    ImVec2 lable_pos = ImVec2(485, 5+70+5);// 子窗口位置
    ImGui::SetNextWindowSize(lable_size);
    ImGui::SetNextWindowPos(lable_pos);
    ImGui::Begin("持仓信息", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    ImGui::Text("持仓信息:");
    
    StockPosition pos1;
    if(getStockPosition("600104.SH", &pos1))
    {
        ImGui::Text("股票1:%d",pos1.quantity);
    }
    ImGui::End();
}

// 右侧_显示股票分析数据
void show_analysis_data()
{
    static bool is_first_time = true;
    // 当前股票的分析结果
    static std::vector<std::string> stock_analysis_info_string;
    if(is_first_time)
    {
        is_first_time = false;
        g_timeline.registerCallback_after([](const std::string& date) {
            // std::cout<<"#729 显示当前股票分析数据 BEGIN"<<std::endl;            
            if(g_current_stock_code.empty())return;
            // 取对应的股票分析数据
            two_analyzer &analyzers = g_analyzer_map[g_current_stock_code];
            StockAnalyzer *analyzer = analyzers.analyzer;
            stock_analyzer_2 *analyzer2 = analyzers.analyzer2;
            stock_analyzer_data data_analysis = analyzeStockData(analyzer, g_timeline.getCurrentDate().c_str());

            stock_analysis_info_string.clear();
            char buffer[100];

            // 30日MACD零线水平
            sprintf(buffer, "%.2f", data_analysis.arrange_value);
            stock_analysis_info_string.push_back(std::string("30日MACD零线水平")+buffer);// MACD负值越多,这个值就越小, 越小胜率就越高.
            g_need_render=2;
            
            // // macd 底背离
            // std::vector<double> &macd_valleys = data_analysis.macd_valleys;
            // std::vector<double> &macd_valleys_price = data_analysis.macd_valleys_price;
            // bool is_data_right = true;
            // if(macd_valleys.size()==0||macd_valleys_price.size()==0)
            // {
            //     is_data_right = false;
            // }
            // if(is_data_right)
            // {
            //     std::string str_valleys = "谷值:";
            //     std::string str_valleys_price = "谷价:";
            //     std::vector<double> macd_depart_calculate;// 计算背离的情况
            //     double total_valleys=0;
            //     double total_valleys_price=0;
            //     for(size_t i=0;i<macd_valleys.size();++i)
            //     {
            //         // if(i<macd_valleys.size()-1)
            //         // {
            //         //     double macd_depart = macd_valleys[i]-macd_valleys[i+1];// 这个应该大于零
            //         //     double price_depart = macd_valleys_price[i+1]-macd_valleys_price[i];// 相对于上面,顺序是反过来的, 应该是大于零的数(如果有背离的话)                    
            //         //     macd_depart_calculate.push_back(macd_depart*price_depart);
            //         // }
            //         // sprintf(buffer, "%.2f,",macd_valleys[i]);
            //         // str_valleys+=buffer;
            //         // sprintf(buffer, "%.2f,",macd_valleys_price[i]);
            //         // str_valleys_price+=buffer;
            //         total_valleys+=macd_valleys[i];
            //         total_valleys_price += macd_valleys_price[i];
            //     }
            //     double average_valleys = total_valleys/macd_valleys.size();
            //     sprintf(buffer, "平均:%.2f,",average_valleys);
            //     str_valleys+=buffer;
            //     stock_analysis_info_string.push_back(str_valleys);
            //     double average_valleys_price = total_valleys_price/macd_valleys.size();
            //     sprintf(buffer, "平均:%.2f,",average_valleys_price);
            //     str_valleys_price+=buffer;
            //     stock_analysis_info_string.push_back(str_valleys_price);
            //     // 输出差值:
            //     sprintf(buffer, "价格差值:%.2f,",average_valleys_price-macd_valleys_price[0]);
            //     stock_analysis_info_string.push_back(buffer);
            //     sprintf(buffer, "MACD差值:%.2f,",macd_valleys[0]-average_valleys);
            //     stock_analysis_info_string.push_back(buffer);
            //     // // 输出背离计算值:
            //     // std::string str_depart_calc="背计:";
            //     // double total_depart_calculate=0;
            //     // for(size_t i=0;i<macd_depart_calculate.size();++i)
            //     // {
            //     //     sprintf(buffer, "%.2f,",macd_depart_calculate[i]);
            //     //     total_depart_calculate+=macd_depart_calculate[i];
            //     //     str_depart_calc+=buffer;
            //     // }
            //     //stock_analysis_info_string.push_back(str_depart_calc);
            //     // // 输出统计值:
            //     // std::string str_total_depart_calc="背离统计:";
            //     // sprintf(buffer, "%.2f,",total_depart_calculate);
            //     // str_total_depart_calc+=buffer;
            //     // stock_analysis_info_string.push_back(str_total_depart_calc);
            // }

            // std::cout<<"#729 显示当前股票分析数据 END"<<std::endl;

            sprintf(buffer, "Ma120:%.2f", data_analysis.ma120," 价倍:%.2f",data_analysis.currentPrice/data_analysis.ma120);
            stock_analysis_info_string.push_back(buffer);
            // 120线与现价的关系
            if( data_analysis.ma120*1.5<data_analysis.currentPrice)
            {
                stock_analysis_info_string.push_back("涨过120日线1.5倍");
            }

            // 90天内MACD有没有大的波动
            if(data_analysis.macd_depart_speed_up_days>0)
            {
                stock_analysis_info_string.push_back("MACD背离见底 macd_depart_speed_up");
            }
            // MACD活跃度:
            sprintf(buffer, "MACD活跃:%.2f", data_analysis.macd_activity_rate);
            stock_analysis_info_string.push_back(buffer);

            // 量:
            sprintf(buffer, "量突破:%.2f",data_analysis.vol/data_analysis.volMa60);
            stock_analysis_info_string.push_back(buffer);
            if(data_analysis.vol>data_analysis.lastVol)
            {
                stock_analysis_info_string.push_back("增量");
            }
            else
            {
                stock_analysis_info_string.push_back("缩量");
            }

            // 120日面积:
            std::string str_ma120_area="120面积:";
            stock_analysis_info_string.push_back(str_ma120_area);
            for(size_t i=0;i<data_analysis.ma120Area.size();++i)
            {
                sprintf(buffer, "%s : %.2f\n",data_analysis.ma120Area[i].first.c_str(),data_analysis.ma120Area[i].second);
                stock_analysis_info_string.push_back(buffer);
                // str_ma120_area+=buffer;
            }

            //data_analysis.vol
        });
    }
    
    // 创建窗口，禁用滚动条
    ImVec2 lable_size = ImVec2(200, 195);// 标签大小
    ImVec2 lable_pos = ImVec2(485, 80+195+5);// 子窗口位置
    ImGui::SetNextWindowSize(lable_size);
    ImGui::SetNextWindowPos(lable_pos);
    ImGui::Begin("##show_analysis_data", nullptr, ImGuiWindowFlags_NoScrollbar| ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse| ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoTitleBar);
    //ImGui::Text("90日价格位置:");
    for (const std::string &info: stock_analysis_info_string)
    {
        ImGui::Text(info.c_str());
    }
    ImGui::End();
}

void render(GLFWwindow* window)
{
    if(g_need_render-- > 0)
    {
        // 开始新的 ImGui 帧
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        // 设置窗口内边距为零
        ImGui::GetStyle().WindowPadding = ImVec2(0.0f, 0.0f);

        // 日期标签:
        label_today();
        // K线绘制
        draw_K_line();
        // MACD
        draw_MACD();
        // volume 成交量:
        sub_window_volume();
        // KDJ:
        draw_KDJ();
        // 按钮:
        button_next_day();

        // 左侧:
        // 自动:
        button_auto();
        // 换股票:
        button_change_stock();
        // 导出按钮:
        button_export();

        // 右侧
        // 资金
        show_fund();
        // 持仓信息
        show_position_info();
        // 股票分析数据:
        show_analysis_data();

        // 渲染 ImGui
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);
    }
    //g_need_render=1;
}


// 键盘回调函数
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, GLFW_TRUE);
    }
    if (action == GLFW_PRESS) {
        // std::cout << "Key " << key << " pressed." << std::endl;
        g_need_render=1;
    } else if (action == GLFW_RELEASE) {
        g_need_render=1;
        // std::cout << "Key " << key << " released." << std::endl;
    }
}

// 鼠标按钮回调函数
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
    if (action == GLFW_PRESS) {
        g_need_render=1;
        // std::cout << "Mouse button " << button << " pressed." << std::endl;
    } else if (action == GLFW_RELEASE) {
        g_need_render=1;
        // std::cout << "Mouse button " << button << " released." << std::endl;
    }
}

// 鼠标移动回调函数
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
    // std::cout << "Mouse moved to: (" << xpos << ", " << ypos << ")" << std::endl;
    // ImGui_ImplGlfw_CursorPosCallback(window, xpos, ypos);
    
    g_need_render=1;

    // 记录鼠标坐标到mouse_pos模块
    setMousePos(static_cast<int>(xpos), static_cast<int>(ypos));
}

// 初始化 ImGui  加载中文字体
void setupImGui(GLFWwindow* window) {

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;// 后面这句的目的是防止io未使用报错
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init("#version 330");


    // // 加载支持中文的字体
    // // 为能显示中文, 需要更多的设置
    // ImWchar ranges[] = {
    //     0x0020, 0x00FF, // 基本拉丁字符
    //     0x4e00, 0x9fa5, // 中文字符
    //     0
    // };
    ImFont* font = io.Fonts->AddFontFromFileTTF("simhei.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesChineseFull());
    if (!font) {
        std::cerr << "Failed to load font!" << std::endl;
    }

    g_fontSmall = io.Fonts->AddFontFromFileTTF("simhei.ttf", 14.0f, nullptr, io.Fonts->GetGlyphRangesChineseFull());

}



int main() {
    // 设置控制台输出和输入为 UTF-8
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleCP(CP_UTF8);

    // samples:
    const char str_sample_first[255] = "./stock_csv_files_2/002415.SZ.csv";
    const char str_sample_filst_code[255] = "002415.SZ";
    const char str_sample_dictory[255] = "./stock_csv_files_2/";

    // 加载股票数据
    g_stockData = StockDataLoader::loadFromCSV(str_sample_first);//920108.BJ.csv // 600104.SH.csv
    // 给个当前股票代码, 使不用手输代码就可以看右侧的分析结果显示
    g_current_stock_code = str_sample_filst_code;
    if (g_stockData.empty()) {
        std::cerr << "Failed to load stock data" << std::endl;
        return -1;
    }

    // 加成所有的股票数据:
    bool is_load_success = loadAllStockData(str_sample_dictory);
    if(!is_load_success)
    {
        std::cerr << "!!!!    ERR 366 加载所有股票数据失败" << std::endl;
        return -1;
    }
    // 为所有的股票生成对应的分析器
    for(auto& stock : getAllStockCodes())
    {
        const std::vector<StockData>* data_1 = getStockData(stock.c_str());
        two_analyzer analyzers;
        analyzers.analyzer = createStockAnalyzer(data_1->data(), data_1->size());
        analyzers.analyzer2 = new stock_analyzer_2();
        // analyzers.analyzer2->setStartHold();
        if(stock ==  "300750.SZ"  )
        {
            analyzers.analyzer2->setBuyStack(234.23,100);
        }
        else if(stock == "600436.SH")
        {
            analyzers.analyzer2->setBuyStack(202.5,100);
        }
        else if(stock == "300274.SZ")
        {
            analyzers.analyzer2->setBuyStack(62.54,100);
        }
        else if(stock == "002415.SZ.csv")
        {
            analyzers.analyzer2->setBuyStack(27.96,100);
        }
        else if(stock == "300827.SZ")
        {
            analyzers.analyzer2->setBuyStack(28.12,100);
        }
        else if(stock == "300142.SZ")
        {
            analyzers.analyzer2->setBuyStack(10.67,200);
        }
        else if(stock == "600089.SH")
        {
            analyzers.analyzer2->setBuyStack(11.41,100);
        }
        else if(stock == "300140.SZ")
        {
            analyzers.analyzer2->setBuyStack(5.26,100);
        }
        else if(stock == "600516.SH")
        {
            analyzers.analyzer2->setBuyStack(4.72,100);
        }
        g_analyzer_map[stock] = analyzers;
    }

    // 赌徒
    for(size_t i=0;i<30;++i)
    {
        g_gamblers.push_back(Gambler());// 1
    }
    // g_gamblers.push_back(Gambler());// 2
    // g_gamblers.push_back(Gambler());// 3
    // g_gamblers.push_back(Gambler());// 4
    // g_gamblers.push_back(Gambler());// 5
    // g_gamblers.push_back(Gambler());// 6
    // g_gamblers.push_back(Gambler());// 7
    // g_gamblers.push_back(Gambler());// 8
    // g_gamblers.push_back(Gambler());// 9
    // g_gamblers.push_back(Gambler());// 10

    // 转换为K线数据并初始化
    std::vector<StockData> klineData = g_stockData;
    
    // 初始化 GLFW
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    // 创建 GLFW 窗口
    GLFWwindow* window = glfwCreateWindow(g_main_window_width, g_main_window_height, "Stock K Line with ImGui", nullptr, nullptr);
    if (!window) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // 初始化 GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cerr << "Failed to initialize GLAD" << std::endl;
        glfwTerminate();
        return -1;
    }

    // 设置回调函数
    glfwSetKeyCallback(window, key_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetCursorPosCallback(window, cursor_position_callback);

    setupImGui(window);

    // 初始化K线数据 用于绘制单只股票的信息
    initKLineData(klineData);
    setMACDData(klineData);
    initVolumeChart();
    setVolumeData(klineData);
    setKDJChartData(klineData);       

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        render(window);
    }

    // 清理资源
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}
